package com.wpen.unit.service.job.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.wpen.unit.AppVariables;
import com.wpen.unit.cvt.job.DependonCvt;
import com.wpen.unit.enums.DependType;
import com.wpen.unit.enums.YN;
import com.wpen.unit.infra.mybatis.job.po.BatchInfoPo;
import com.wpen.unit.infra.mybatis.job.po.DependonPo;
import com.wpen.unit.infra.mybatis.job.po.TaskInfoPo;
import com.wpen.unit.infra.repository.job.BatchInfoRepository;
import com.wpen.unit.infra.repository.job.DependonRepository;
import com.wpen.unit.infra.repository.job.TaskInfoRepository;
import com.wpen.unit.service.job.DependonService;
import com.wpen.unit.utils.IdUtil;
import com.wpen.unit.utils.StringUtil;
import com.wpen.unit.web.dto.job.DependonAddDependsRequest;
import com.wpen.unit.web.dto.job.DependonAddRequest;
import com.wpen.unit.web.dto.job.DependonAddResponse;
import com.wpen.unit.web.dto.job.DependonBatchListRequest;
import com.wpen.unit.web.dto.job.DependonDelRequest;
import com.wpen.unit.web.dto.job.DependonDelResponse;
import com.wpen.unit.web.dto.job.DependonListRequest;
import com.wpen.unit.web.dto.job.DependonListResponse;
import com.wpen.unit.web.dto.job.DependonListRowsResponse;
import com.wpen.unit.web.dto.job.DependonMapBatchRequest;
import com.wpen.unit.web.dto.job.DependonMapRequest;
import com.wpen.unit.web.dto.job.DependonMapResponse;
import com.wpen.unit.web.dto.job.DependonMapRowsResponse;

@Service
public class DependonServiceImpl implements DependonService {

	@Autowired
	private DependonRepository dependonRepository;
	@Autowired
	private TaskInfoRepository taskInfoRepository;
	@Autowired
	private BatchInfoRepository batchInfoRepository;

	@Override
	public DependonMapResponse queryBatchMapDependon(DependonMapBatchRequest dependonMapRequest) {
		String biz = dependonMapRequest.getBizCode();
		// 查询当前batch下所有task
		List<DependonPo> dependonPos = dependonRepository.queryAllBatchs(biz);

		DependonMapResponse response = new DependonMapResponse();

		Map<String, DependonPo> nodeDos = new HashMap<>();
		Map<String, Integer> levelNums = new LinkedHashMap<>();
		Map<String, List<DependonPo>> parent2Childs = new HashMap<>();
		for (DependonPo dependonPo : dependonPos) {
			String oneKey = dependonPo.getBizCode() + "|" + dependonPo.getBatchCode() + "|"
					+ dependonPo.getTaskCode() + "|" + dependonPo.getJobCode();
			nodeDos.put(oneKey, dependonPo);

			String parentKey = dependonPo.getDpdonBizCode() + "|" + dependonPo.getDpdonBatchCode() + "|"
					+ dependonPo.getDpdonTaskCode() + "|" + dependonPo.getDpdonJobCode();
			if (parent2Childs.containsKey(parentKey)) {
				List<DependonPo> listParentChild = parent2Childs.get(parentKey);
				listParentChild.add(dependonPo);
			} else {
				List<DependonPo> listParentChild = new ArrayList<>();
				listParentChild.add(dependonPo);
				parent2Childs.put(parentKey, listParentChild);
			}
		}
		// 递归排层
		DependonPo root = new DependonPo();
		root.setBizCode(AppVariables.DEPENDON_PHD);
		root.setBatchCode(AppVariables.DEPENDON_PHD);
		root.setTaskCode(AppVariables.DEPENDON_PHD);
		root.setJobCode(AppVariables.DEPENDON_PHD);
		loopCheckLevel(root, parent2Childs, levelNums, 0);

		List<DependonMapRowsResponse> nodes = response.getNodes();
		Map<Integer, Integer> nodeCols = new HashMap<>();
		// node节点
		for (Map.Entry<String, Integer> entry : levelNums.entrySet()) {
			String key = entry.getKey();
			Integer val = entry.getValue();
			if (nodeCols.containsKey(val)) {
				nodeCols.put(val, nodeCols.get(val) + 1);
			} else {
				nodeCols.put(val, 1);
			}
			DependonPo dpnPo = nodeDos.get(key);
			DependonMapRowsResponse node = new DependonMapRowsResponse();
			node.setSelfType(dpnPo.getSelfType());
			node.setBizCode(dpnPo.getBizCode());
			node.setBatchCode(dpnPo.getBatchCode());
			node.setTaskCode(dpnPo.getTaskCode());
			node.setJobCode(dpnPo.getJobCode());
			node.setX(nodeCols.get(val));
			node.setY(val);
				node.setName(dpnPo.getBatchCode()); //
			nodes.add(node);
		}

		Integer maxCol = 1;
		Integer maxRow = 1;
		for (Map.Entry<Integer, Integer> entry : nodeCols.entrySet()) {
			if (entry.getKey() > maxRow) {
				maxRow = entry.getKey();
			}
			if (entry.getValue() > maxCol) {
				maxCol = entry.getValue();
			}
		}
		response.setMaxCol(maxCol);
		List<DependonMapRowsResponse> links = response.getLinks();
		for (DependonPo dependonPo : dependonPos) {
			DependonMapRowsResponse rowsResponse = DependonCvt.INSTANCE.queryMapRowDo2Dto(dependonPo);
			rowsResponse.setStatus("");
			links.add(rowsResponse);
		}

		return response;
	}

	@Override
	public DependonMapResponse queryMapDependon(DependonMapRequest dependonMapRequest) {
		String biz = dependonMapRequest.getBizCode();
		String batch = dependonMapRequest.getBatchCode();
		String task = dependonMapRequest.getTaskCode();
		Boolean includeChild = dependonMapRequest.getIncludeChild();

		DependonMapResponse response = new DependonMapResponse();
		//
		BatchInfoPo batchInfoPo = batchInfoRepository.queryByCode(biz, batch);

		if (StringUtil.isEmpty(task)) {
			// 查询当前batch下所有task
			List<DependonPo> dependonPos = dependonRepository.queryAllSubByParent(biz, batch, task, includeChild);

			Map<String, DependonPo> nodeDos = new HashMap<>();
			Map<String, Integer> levelNums = new LinkedHashMap<>();
			Map<String, List<DependonPo>> parent2Childs = new HashMap<>();
			for (DependonPo dependonPo : dependonPos) {
				String oneKey = dependonPo.getBizCode() + "|" + dependonPo.getBatchCode() + "|"
						+ dependonPo.getTaskCode() + "|" + dependonPo.getJobCode();
				nodeDos.put(oneKey, dependonPo);

				String parentKey = dependonPo.getDpdonBizCode() + "|" + dependonPo.getDpdonBatchCode() + "|"
						+ dependonPo.getDpdonTaskCode() + "|" + dependonPo.getDpdonJobCode();
				if (parent2Childs.containsKey(parentKey)) {
					List<DependonPo> listParentChild = parent2Childs.get(parentKey);
					listParentChild.add(dependonPo);
				} else {
					List<DependonPo> listParentChild = new ArrayList<>();
					listParentChild.add(dependonPo);
					parent2Childs.put(parentKey, listParentChild);
				}
			}
			// 递归排层
			DependonPo root = new DependonPo();
			root.setId(batchInfoPo.getId());
			root.setBizCode(batchInfoPo.getBizCode());
			root.setBatchCode(batchInfoPo.getBatchCode());
			root.setTaskCode(AppVariables.DEPENDON_PHD);
			root.setJobCode(AppVariables.DEPENDON_PHD);
			loopCheckLevel(root, parent2Childs, levelNums, 1);

			List<DependonMapRowsResponse> nodes = response.getNodes();
			DependonMapRowsResponse nodeRoot = new DependonMapRowsResponse();
			nodeRoot.setSelfType(DependType.Batch.value());
			nodeRoot.setBizCode(batchInfoPo.getBizCode());
			nodeRoot.setBatchCode(batchInfoPo.getBatchCode());
			nodeRoot.setTaskCode(AppVariables.DEPENDON_PHD);
			nodeRoot.setJobCode(AppVariables.DEPENDON_PHD);
			nodeRoot.setName(batchInfoPo.getBatchName());
			nodeRoot.setX(1);
			nodeRoot.setY(1);
			nodes.add(nodeRoot);
			Map<Integer, Integer> nodeCols = new HashMap<>();
			// node节点
			for (Map.Entry<String, Integer> entry : levelNums.entrySet()) {
				String key = entry.getKey();
				Integer val = entry.getValue();
				if (nodeCols.containsKey(val)) {
					nodeCols.put(val, nodeCols.get(val) + 1);
				} else {
					nodeCols.put(val, 1);
				}
				DependonPo dpnPo = nodeDos.get(key);
				DependonMapRowsResponse node = new DependonMapRowsResponse();
				node.setSelfType(dpnPo.getSelfType());
				node.setBizCode(dpnPo.getBizCode());
				node.setBatchCode(dpnPo.getBatchCode());
				node.setTaskCode(dpnPo.getTaskCode());
				node.setJobCode(dpnPo.getJobCode());
				node.setX(nodeCols.get(val));
				node.setY(val);
				TaskInfoPo taskInfoPo = taskInfoRepository.queryByCode(biz, batch, dpnPo.getTaskCode());
				if (taskInfoPo == null) {
					node.setName(dpnPo.getTaskCode() + "-" + dpnPo.getJobCode()); //
				} else {
					node.setName(taskInfoPo.getTaskName()); //
				}
				nodes.add(node);
			}

			Integer maxCol = 1;
			Integer maxRow = 1;
			for (Map.Entry<Integer, Integer> entry : nodeCols.entrySet()) {
				if (entry.getKey() > maxRow) {
					maxRow = entry.getKey();
				}
				if (entry.getValue() > maxCol) {
					maxCol = entry.getValue();
				}
			}
			response.setMaxCol(maxCol);
			List<DependonMapRowsResponse> links = response.getLinks();
			for (DependonPo dependonPo : dependonPos) {
				DependonMapRowsResponse rowsResponse = DependonCvt.INSTANCE.queryMapRowDo2Dto(dependonPo);
				rowsResponse.setStatus("");
				links.add(rowsResponse);
			}
		}
		return response;
	}

	public void loopCheckLevel(DependonPo dependonPo, Map<String, List<DependonPo>> parent2Childs,
			Map<String, Integer> levelNums, int level) {
		String parentKey = dependonPo.getBizCode() + "|" + dependonPo.getBatchCode() + "|" + dependonPo.getTaskCode()
				+ "|" + dependonPo.getJobCode();
		List<DependonPo> listSub = parent2Childs.get(parentKey);
		if (listSub != null && !listSub.isEmpty()) {
			for (DependonPo dependonPo2 : listSub) {
				String oneKey = dependonPo2.getBizCode() + "|" + dependonPo2.getBatchCode() + "|"
						+ dependonPo2.getTaskCode() + "|" + dependonPo2.getJobCode();
				levelNums.put(oneKey, level + 1);
			}
			for (DependonPo dependonPo2 : listSub) {
				loopCheckLevel(dependonPo2, parent2Childs, levelNums, level + 1);
			}
		}
	}

	@Override
	public DependonListResponse queryListDependon(DependonListRequest dependonListRequest) {
		// 数据库查询
		DependonPo dependonPo = DependonCvt.INSTANCE.queryListDto2Do(dependonListRequest);

		List<DependonPo> dependonPoLists = dependonRepository.queryAllPrtByOwn(dependonPo.getBizCode(),
				dependonPo.getBatchCode(), dependonPo.getTaskCode(), null, dependonListRequest.getIncludeParent(),
				dependonListRequest.getIncludeSub());

		// 返回响应信息
		DependonListResponse dependonListResponse = new DependonListResponse();
		if (dependonPoLists != null) {
			List<DependonListRowsResponse> listRows = dependonListResponse.getRows();
			for (DependonPo inDependonPo : dependonPoLists) {
				DependonListRowsResponse row = DependonCvt.INSTANCE.queryListRowDo2Dto(inDependonPo);
				listRows.add(row);
			}
			dependonListResponse.setRows(listRows);
		}

		return dependonListResponse;
	}

	@Override
	public DependonListResponse queryBatchListDependon(DependonBatchListRequest dependonBatchListRequest) {
		// 数据库查询
		DependonPo dependonPo = DependonCvt.INSTANCE.queryBatchListDto2Do(dependonBatchListRequest);

		List<DependonPo> dependonPoLists = dependonRepository.queryList(0, 0, dependonPo);

		// 返回响应信息
		DependonListResponse dependonListResponse = new DependonListResponse();
		if (dependonPoLists != null) {
			List<DependonListRowsResponse> listRows = dependonListResponse.getRows();
			for (DependonPo inDependonPo : dependonPoLists) {
				DependonListRowsResponse row = DependonCvt.INSTANCE.queryListRowDo2Dto(inDependonPo);
				listRows.add(row);
			}
			dependonListResponse.setRows(listRows);
		}

		return dependonListResponse;
	}

	@Override
	@Transactional
	public DependonAddResponse addDependon(DependonAddRequest dependonAddRequest) {
		List<DependonAddDependsRequest> depends = dependonAddRequest.getDepends();
		if (depends == null || depends.isEmpty()) {
			return new DependonAddResponse();
		}
		// 上送要上送所有
		String biz = depends.get(0).getBizCode();
		String batch = depends.get(0).getBatchCode();
		String task = depends.get(0).getTaskCode();
		String job = depends.get(0).getJobCode();

		List<DependonPo> dependonPoLists = dependonRepository.queryAllPrtByOwn(biz, batch, task, job, true, false);
		// 之前的全部删除，新的全部添加
		List<DependonPo> addPos = new ArrayList<>();
		for (DependonAddDependsRequest addDependsRequest : depends) {
			DependonPo dependonPo = DependonCvt.INSTANCE.addDto2Do(addDependsRequest);
			if (StringUtil.isEmpty(dependonPo.getTaskCode())) {
				dependonPo.setTaskCode(AppVariables.DEPENDON_PHD);
			}
			if (StringUtil.isEmpty(dependonPo.getDpdonTaskCode())) {
				dependonPo.setDpdonTaskCode(AppVariables.DEPENDON_PHD);
			}
			if (StringUtil.isEmpty(dependonPo.getJobCode())) {
				dependonPo.setJobCode(AppVariables.DEPENDON_PHD);
			}
			if (StringUtil.isEmpty(dependonPo.getDpdonJobCode())) {
				dependonPo.setDpdonJobCode(AppVariables.DEPENDON_PHD);
			}
			dependonPo.setId(IdUtil.nextId());
			dependonPo.setCreateTime(new Date());
			dependonPo.setVersion(1);
			addPos.add(dependonPo);
		}
		// 保存数据
		dependonRepository.insertBatch(addPos);
		if (dependonPoLists != null && dependonPoLists.size() > 0) {
			List<Long> idLists = new ArrayList<>();
			dependonPoLists.forEach(po -> {
				idLists.add(po.getId());
			});
			Long[] ids = new Long[idLists.size()];
			ids = idLists.toArray(ids);
			dependonRepository.deleteByIds(ids);
		}

		// 返回响应信息
		DependonAddResponse dependonAddResponse = new DependonAddResponse();
		List<DependonPo> dependonRsLists = dependonRepository.queryAllPrtByOwn(biz, batch, task, job, false, false);
		// 返回响应信息
		if (dependonRsLists != null) {
			List<DependonListRowsResponse> listRows = dependonAddResponse.getRows();
			for (DependonPo inDependonPo : dependonRsLists) {
				DependonListRowsResponse row = DependonCvt.INSTANCE.queryListRowDo2Dto(inDependonPo);
				listRows.add(row);
			}
			dependonAddResponse.setRows(listRows);
		}
		return dependonAddResponse;
	}

	@Override
	@Transactional
	public DependonDelResponse delDependon(DependonDelRequest dependonDelRequest) {
		Long id = dependonDelRequest.getId();
		// 持久化操作
		DependonPo dependonPo = dependonRepository.queryById(id);
		if (dependonPo != null) {
			// 查询自己还有没有其他依赖，没有：关联到父。 有：直接删除
			List<DependonPo> dependonPoLists = dependonRepository.queryAllPrtByOwn(dependonPo.getBizCode(),
					dependonPo.getBatchCode(), dependonPo.getTaskCode(), null, true, false);
			if (dependonPoLists != null && dependonPoLists.size() > 1) {
				// 更新数据
				dependonRepository.deleteById(id);
			} else {
				dependonRepository.deleteById(id);
				DependonPo dependonPoLinkBatch = new DependonPo();
				dependonPoLinkBatch.setId(IdUtil.nextId());
				dependonPoLinkBatch.setBizCode(dependonPo.getBizCode());
				dependonPoLinkBatch.setBatchCode(dependonPo.getBatchCode());
				dependonPoLinkBatch.setTaskCode(dependonPo.getTaskCode());
				dependonPoLinkBatch.setJobCode(dependonPo.getJobCode());
				dependonPoLinkBatch.setDpdonBizCode(dependonPo.getBizCode());
				dependonPoLinkBatch.setDpdonBatchCode(dependonPo.getBatchCode());
				dependonPoLinkBatch.setDpdonTaskCode(AppVariables.DEPENDON_PHD);
				dependonPoLinkBatch.setDpdonJobCode(AppVariables.DEPENDON_PHD);
				dependonPoLinkBatch.setSelfType(dependonPo.getSelfType());
				dependonPoLinkBatch.setCreateTime(new Date());
				dependonPoLinkBatch.setEnabled(YN.Yes.value());
				dependonPoLinkBatch.setVersion(1);
				dependonRepository.insert(dependonPoLinkBatch);
			}
		}

		// 返回响应信息
		DependonDelResponse dependonDelResponse = new DependonDelResponse();
		return dependonDelResponse;
	}

}
